home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / comm / tcp / MUIAdt.lha / src / ftp.c < prev    next >
C/C++ Source or Header  |  1994-09-01  |  8KB  |  405 lines

  1. /*
  2.  *  This code is pretty much the unix adt distribution ftp code
  3.  *   (mostly because I have no idea how to do it myself :-))
  4.  */
  5.  
  6. #include "adt.h"
  7.  
  8. #include <exec/libraries.h>
  9. #include <dos/dosextens.h>
  10. #include <dos/dos.h>
  11. #include <clib/dos_protos.h>
  12. #include <libraries/mui.h>
  13. #include <clib/alib_protos.h>
  14.  
  15. #include <stdio.h>
  16. #include <stdarg.h>
  17. #include <stdlib.h>
  18.  
  19. #include <bsdsocket.h>
  20. #include <sys/time.h>
  21. #include <sys/param.h>
  22. #include <sys/types.h>
  23. #include <sys/socket.h>
  24. #include <sys/ioctl.h>
  25.  
  26. #include <sys/time.h>
  27.  
  28. #include <netinet/in.h>
  29. #include <netinet/tcp.h>
  30. #include <arpa/ftp.h>
  31. #include <arpa/telnet.h>
  32.  
  33. #include <string.h>
  34. #include <netdb.h>
  35. #include <fcntl.h>
  36. #include <signal.h>
  37. #include <errno.h>
  38. #include <ios1.h>
  39. #include <ctype.h>
  40.  
  41.  
  42. #define NBBY    8                /* number of bits in a byte */
  43. #define NFDBITS (sizeof(fd_mask) * NBBY)        /* bits per mask */
  44. #define FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
  45. #define FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
  46. #define FD_ISSET(n, p)  ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
  47. #define FD_ZERO(p)      bzero((char *)(p), sizeof(*(p)))
  48.  
  49. #ifndef MAXHOSTNAMELEN
  50. #define MAXHOSTNAMELEN 64
  51. #endif
  52.  
  53. #undef BUFSIZ
  54. #define BUFSIZ 1024
  55.  
  56. #define s_close(x) CloseSocket(x)
  57.  
  58. int sgetc(int);
  59. char *ftp_connect(char *host, char *path);
  60. int ftp_getreply(int);
  61. int ftp_command(char *, ...);
  62. void ftp_lostpeer(void);
  63. int ftp_login(void);
  64. int ftp_get(char *name, LONG size, char *local);
  65. int ftp_initconn(void);
  66. int ftp_dataconn(void);
  67.  
  68. int din, fin, fout;
  69. FILE *dout;
  70.  
  71. BOOL connected = FALSE;
  72. int fdata=-1, pgrp, code;
  73. struct sockaddr_in myctladdr, data_addr;
  74.  
  75. char *login, *hostname;
  76.  
  77. extern APTR app, get_gauge;
  78.  
  79. int sgetc(int sock)
  80. {
  81.     unsigned char c;
  82.     fd_set rd,ex;
  83.     long flgs;
  84.     int n;
  85.  
  86.     struct timeval t;
  87.     t.tv_sec = 10L;
  88.     t.tv_usec = 0;
  89.  
  90.     FD_ZERO(&rd);
  91.     FD_ZERO(&ex);
  92.  
  93.     FD_SET(sock,&rd);
  94.     FD_SET(sock,&ex);
  95.     flgs = SIGBREAKF_CTRL_D;
  96.  
  97.     WaitSelect(16,&rd,0L,&ex,&t,&flgs);
  98.  
  99.     if (FD_ISSET(sock,&rd))
  100.     {    n = recv(sock, &c, 1, 0);
  101.         if (n == 1)
  102.             return c;
  103.         else return -1;
  104.     }
  105.  
  106.     else return -1;
  107. }
  108.  
  109. char *ftp_connect(char *host, char *path)
  110. {
  111.     struct sockaddr_in server;
  112.     struct servent *sp;
  113.     struct hostent *hp;
  114.     LONG s, len;
  115.  
  116.     if (connected) {
  117.     ftp_command("QUIT");
  118.     if (fout)
  119.         s_close(fout);
  120.     fout = -1;
  121.     connected = FALSE;
  122.     fdata = -1;
  123.     }
  124.  
  125.     sp = getservbyname("ftp", "tcp");
  126.     if ((sp = getservbyname("ftp", "tcp")) == NULL)
  127.     return("*This site does not support FTP/TCP");
  128. /*    hp = gethostbyname(host); */
  129.     if ((hp = gethostbyname(host)) == NULL)
  130.     return("FTP can't connect : Unknown Host");
  131.  
  132.     bzero((char *)&server, sizeof(server));
  133.     bcopy(hp->h_addr, (char *)&server.sin_addr, hp->h_length);
  134.     server.sin_family = hp->h_addrtype;
  135.     server.sin_port = sp->s_port;
  136.     s = socket(AF_INET, SOCK_STREAM, 0);
  137.     if (s < 0)
  138.     return(sys_errlist[errno]);
  139.     if (connect(s, (struct sockaddr const *)&server, sizeof(server)) < 0)
  140.     return(sys_errlist[errno]);
  141.     len = sizeof(myctladdr);
  142.     if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0)
  143.     return(sys_errlist[errno]);
  144.     fout = /*fdopen(s, "w")*/s;
  145.     fin = /*fdopen(s, "r")*/s;
  146. /*    if (fin == NULL ||  fout == NULL) {
  147.     if (fin) fclose(fin);
  148.     if (fout) fclose(fout);
  149.     return(sys_errlist[errno]);
  150.     } */
  151.  
  152.     /* connected it seems */
  153.  
  154.     connected = 1;
  155.  
  156.     if (ftp_getreply(0) > 2) {
  157.     ftp_lostpeer();
  158.     return("Remote protocol error, startup message wrong");
  159.     }
  160.     if (!ftp_login()) {
  161.     ftp_lostpeer();
  162.     return("Connection refused");
  163.     }
  164.  
  165.     /* logged in it seems */
  166.  
  167.     if (ftp_command("TYPE I") != COMPLETE) {
  168.     ftp_lostpeer();
  169.     return("Remote host has closed the connection");
  170.     }
  171.     if (ftp_command("CWD %s", path) != COMPLETE) {
  172.     char message[256];
  173.     ftp_lostpeer();
  174.     sprintf(message, "Could not CD to directory \"%s\"\n", path);
  175.     return(message);
  176.     }
  177.     return(NULL);
  178. }
  179.  
  180. int ftp_getreply(int expecteof)
  181. {
  182.     int c, n;
  183.     int dig;
  184.     int ocode = 0, cont = 0;
  185.  
  186.     for (;;) {
  187.     dig = n = code = 0;
  188.     while ((c = sgetc(fin)) != '\n') {
  189.         if (c == IAC) {                 /* Telnet? */
  190.         switch(c = sgetc(fin)) {
  191.             case WILL:
  192.             case WONT: {
  193.             char temp[20]; int x;
  194.             c = sgetc(fin);
  195.             x = sprintf(temp, "%c%c%c", IAC, DONT, c);
  196.             send(fout, temp, x, NULL);
  197.             break;
  198.             }
  199.  
  200.             case DO:
  201.             case DONT: {
  202.             char temp[20]; int x;
  203.             c = sgetc(fin);
  204.             x = sprintf(temp, "%c%c%c", IAC, WONT, c);
  205.             send(fout, temp, x, NULL);
  206.             break;
  207.             }
  208.  
  209.             default:
  210.             break;
  211.             }
  212.         continue;
  213.         }
  214.         dig++;
  215.         if (c == EOF) {
  216.         if (expecteof) {
  217.             code = 221;
  218.             return(0);
  219.         }
  220.         ftp_lostpeer();
  221.         code = 421;
  222.         return(4);
  223.         }
  224.         if (dig < 4 && isdigit(c))
  225.         code = code * 10 + (c - '0');
  226.         if (dig == 4 && c == '-') {
  227.         if (cont)
  228.             code = 0;
  229.         cont++;
  230.         }
  231.         if (n == 0)
  232.         n = c;
  233.     }
  234.     if (cont && code != ocode) {
  235.         if (ocode == 0)
  236.         ocode = code;
  237.         continue;
  238.     }
  239.     if (code == 421 || ocode == 421)
  240.         ftp_lostpeer();
  241.     return(n - '0');
  242.     }
  243. }
  244.  
  245. /* send an FTP command */
  246.  
  247. int ftp_command(char *fmt, ...)
  248. {
  249.     va_list args;
  250.     char comm[256];
  251.     int len;
  252.  
  253.     va_start(args, fmt);
  254.     len = vsprintf(comm, fmt, args);
  255.     strcpy(&comm[len], "\r\n");
  256.     send(fout, comm, len+2, NULL);
  257.     va_end(args);
  258.     return ftp_getreply(!strncmp(fmt, "QUIT", 4));
  259. }
  260.  
  261. void ftp_lostpeer()
  262. {
  263.     if (connected) {
  264.     if (fout >= 0) {
  265.         shutdown(fout, 2);
  266.         fout = -1;
  267.     }
  268.     if (fdata >= 0) {
  269.         shutdown(fdata, 2);
  270.         close(fdata);
  271.         fdata = -1;
  272.     }
  273.     connected = 0;
  274.     }
  275. }
  276.  
  277.  
  278. int ftp_login()
  279. {
  280.     int n;
  281.  
  282.     hostname = getenv("HOSTNAME");
  283.     login = getenv("USERNAME");
  284.     n = ftp_command("USER ftp");
  285.     if (n == CONTINUE)
  286.     n = ftp_command("PASS %s@%s", login, hostname);
  287.     if (n == CONTINUE)
  288.     n = ftp_command("ACCT %s@%s", login, hostname);
  289.     if (n == COMPLETE)
  290.     return(1);
  291.     return(0);
  292. }
  293.  
  294. /* return 0 on success */
  295. int ftp_get(char *name, LONG size, char *local)
  296. {
  297.     char *buffer;
  298.     int bytes=0, d=0, c, retval=1;
  299.     ULONG signal;
  300.  
  301.     if (ftp_initconn()) {
  302.     code = -1;
  303.     return(1);
  304.     }
  305.     if (ftp_command("RETR %s", name) != PRELIM)
  306.     return(1);
  307.     din = ftp_dataconn();
  308.     if (din == NULL)
  309.     goto abort;
  310.     dout = fopen(local, "w");
  311.     if (dout == NULL)
  312.     goto abort;
  313.     buffer = malloc(BUFSIZ);
  314.     if (buffer == NULL)
  315.     goto abort;
  316.  
  317.     set(get_gauge, MUIA_Gauge_Current, 0);
  318.     set(get_gauge, MUIA_Gauge_InfoText, name);
  319.     set(get_gauge, MUIA_Gauge_Max, size);
  320.  
  321.     DoMethod(app, MUIM_Application_Input, &signal);
  322.     while ((c = recv(din, buffer, BUFSIZ, NULL)) > 0) {
  323.     if ((d = write(fileno(dout), buffer, c)) != c) break;
  324.     bytes += c;
  325.     if (size != 0)
  326.         set(get_gauge, MUIA_Gauge_Current, bytes);
  327.     if(DoMethod(app, MUIM_Application_Input, &signal) == ID_GetAbort) {
  328.         retval = 2;
  329.         goto abort;
  330.     }
  331.     }
  332.     if (d < c)
  333.     set(get_gauge, MUIA_Gauge_InfoText, "Error Writing file");
  334.  
  335.     set(get_gauge, MUIA_Gauge_InfoText, NULL);
  336.     free(buffer);
  337.     fclose(dout);
  338.     s_close(din);
  339.     ftp_getreply(0);
  340.     return(0);
  341.  
  342. abort:
  343.     code = -1;
  344.     free(buffer);
  345.     if (fdata >= 0) {
  346.     close(fdata);
  347.     fdata = -1;
  348.     }
  349.     if (din)
  350.        s_close(din);
  351.     if (dout)
  352.     fclose(dout);
  353.     return(retval);
  354. }
  355.  
  356. int ftp_initconn()
  357. {
  358.     register char *p, *a;
  359.     int result;
  360.     LONG len;
  361.  
  362.     data_addr = myctladdr;
  363.     data_addr.sin_port = 0;
  364.     if (fdata != -1)
  365.     close(fdata);
  366.     fdata = socket(AF_INET, SOCK_STREAM, 0);
  367.     if (fdata < 0)
  368.     return(1);
  369.     if (bind(fdata, (struct sockaddr *)&data_addr, sizeof(data_addr)) < 0)
  370.     goto bad;
  371.     len = sizeof(data_addr);
  372.     if (getsockname(fdata, (struct sockaddr *)&data_addr, &len) < 0)
  373.     goto bad;
  374.     listen(fdata, 1);
  375.     a = (char *)&data_addr.sin_addr;
  376.     p = (char *)&data_addr.sin_port;
  377.  
  378. #define UC(b) (((int)b)&0xff)
  379.  
  380.     result = ftp_command("PORT %d,%d,%d,%d,%d,%d", UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
  381.     return(result != COMPLETE);
  382.  
  383. bad:
  384.     close(fdata);
  385.     fdata = -1;
  386.     return(1);
  387. }
  388.  
  389. int ftp_dataconn()
  390. {
  391.     struct sockaddr_in from;
  392.     int s;
  393.     LONG fromlen = sizeof(from);
  394.  
  395.     s = accept(fdata, (struct sockaddr *)&from, &fromlen);
  396.     if (s < 0) {
  397.     s_close(fdata);
  398.     fdata = -1;
  399.     return(NULL);
  400.     }
  401.     s_close(fdata);
  402.     fdata = s;
  403.     return(fdata);
  404. }
  405.